#version 450


layout (binding = 0) uniform sampler2D colorImage;

layout (location = 0) in vec2 inUV;

layout (location = 0) out vec4 outColor;

layout(push_constant) uniform PushConstants
{
    vec2 deltaRes;
    float scale;
    float sharpness;
    int debugIndex;
} pushConstants;


void main(){

    if(pushConstants.debugIndex == 0)
    {
        outColor = vec4(texture( colorImage, inUV ).xyz, 1.0);
        return;
    }
    
	vec3 rgbNW = texture( colorImage, inUV + vec2( -1.0, -1.0 ) * pushConstants.deltaRes ).xyz;
    vec3 rgbNE = texture( colorImage, inUV + vec2( 1.0, -1.0 ) * pushConstants.deltaRes ).xyz;
    vec3 rgbSW = texture( colorImage, inUV + vec2( -1.0, 1.0 ) * pushConstants.deltaRes ).xyz;
    vec3 rgbSE = texture( colorImage, inUV + vec2( 1.0, 1.0 ) * pushConstants.deltaRes ).xyz;
    vec4 rgbaM  = texture( colorImage, inUV);
    vec3 rgbM  = rgbaM.xyz;
    float opacity  = rgbaM.w;
    
    vec3 luma = vec3( 0.299, 0.587, 0.114 );
    
    float lumaNW = dot( rgbNW, luma );
    float lumaNE = dot( rgbNE, luma );
    float lumaSW = dot( rgbSW, luma );
    float lumaSE = dot( rgbSE, luma );
    float lumaM  = dot( rgbM,  luma );
    float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );
    float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );
    

    lumaNE += 1.0 / 384.0;
    vec2 dir;
    dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
    dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
    
    dir = normalize(dir);

    vec2 dir1 = dir * pushConstants.deltaRes * pushConstants.scale;
    vec3 result1 = (texture(colorImage, inUV + dir1).xyz + texture(colorImage, inUV - dir1).xyz) * 0.5;

    float dirAbsMin = min(abs(dir.x), abs(dir.y)) * pushConstants.sharpness;
    vec2 dir2 = clamp(dir / dirAbsMin, -2.0, 2.0) * 2 * pushConstants.deltaRes;
    vec3 result2 = result1 * 0.5 + (texture(colorImage, inUV + dir2).xyz + texture(colorImage, inUV - dir2).xyz) * 0.25;

    float lumaTemp = dot(result2, luma);
    
    if ((lumaTemp < lumaMin) || (lumaTemp > lumaMax)) {
        outColor = vec4(result1, opacity);
    } else {
        outColor = vec4(result2, opacity);
    }
}
